package io.bdmc.modules.bss.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.bdmc.common.annotation.SysLogger1;
import io.bdmc.common.utils.*;
import io.bdmc.common.utils.Constant.ModifyName;
import io.bdmc.modules.bss.entity.FibreCablePoint;
import io.bdmc.modules.bss.entity.FibreFibre;
import io.bdmc.modules.bss.model.FibreCablePointParam;
import io.bdmc.modules.bss.service.IFibreCablePointService;
import io.bdmc.modules.bss.service.IFibreFibreService;
import io.bdmc.modules.sys.controller.AbstractController;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 缆段点 前端控制器
 * </p>
 *
 * @author ping
 * @since 2020-07-02
 */
@Slf4j
// "缆段设施点", description = "/bss/fibre/point")
@RestController
@RequestMapping("/bss/fibre/point")
public class FibreCablePointController extends AbstractController {

	@Autowired
	IFibreCablePointService _fibrecablepointSvs;

	@Autowired
	IFibreFibreService _fibreSvs;

	@GetMapping("/list")
	// "查询单个光缆的所有设施点", notes = "查询单个光缆的所有设施点")
	@RequiresPermissions("bss:fibre:point:list")
	public R list(FibreCablePointParam param) {
		List<FibreCablePoint> list = _fibrecablepointSvs
				.list(new QueryWrapper<FibreCablePoint>().eq("fibre_id", param.getFibreId()).orderByAsc("serial_num"));
		FibreFibre ff = _fibreSvs.getById(param.getFibreId());
		for (FibreCablePoint fibreCablePoint : list) {
			fibreCablePoint.setFibreName(ff.getFibreName());
		}
		return R.ok().putData(list);
	}

	@GetMapping("/info")
	// "查询单个缆段设施点", notes = "查询单个缆段设施点")
	public R info(int pointId) {
		FibreCablePoint p = _fibrecablepointSvs.getById(pointId);
		return R.ok().putData(p);
	}

	@SysLogger1(value = "新增缆段设施点", entityType = FibreCablePoint.class, operationType = ModifyName.ADD)
	@PostMapping("/save")
	// "新增缆段设施点", notes = "新增缆段设施点")
	@RequiresPermissions("bss:fibre:point:save")
	public R save(@RequestBody FibreCablePoint fibrecablepoint) {
		fibrecablepoint.setCreateBy(getUser().getUsername());
		fibrecablepoint.setCreateTime(LocalDateTime.now());
		Boolean b = fibrecablepoint.insert();
		return R.trueOrFalse(b);
	}

	@SysLogger1(value = "修改缆段设施点", entityType = FibreCablePoint.class, operationType = ModifyName.UPDATE)
	@PostMapping("/update")
	// "修改缆段设施点", notes = "修改缆段设施点")
	@RequiresPermissions("bss:fibre:point:update")
	public R update(@RequestBody FibreCablePoint fibrecablepoint) {
		Boolean b = fibrecablepoint.updateById();
		return R.trueOrFalse(b);
	}

	@SysLogger1(value = "设置榄段设施关键点", entityType = FibreCablePoint.class, operationType = ModifyName.UPDATE)
	@PostMapping("/key")
	// "设置榄段设施关键点", notes = "修改缆段设施点")
	public R setKeyPoint(@RequestBody FibreCablePoint point) {
		FibreCablePoint dbKey = _fibrecablepointSvs.getOne(new QueryWrapper<FibreCablePoint>()
				.eq("fibre_id", point.getFibreId()).eq("key_point", true).last("LIMIT 1"));
		if (dbKey != null) {
			dbKey.setKeyPoint(false);
			dbKey.updateById();
		}
		point.setKeyPoint(true);
		Boolean b = point.updateById();
		return R.trueOrFalse(b);
	}

	@SysLogger1(value = "删除缆段点", entityType = FibreCablePoint.class, operationType = ModifyName.DELETE)
	@PostMapping("/delete")
	// "删除缆段设施点", notes = "删除缆段设施点")
	@RequiresPermissions("bss:fibre:point:delete")
	public R delete(@RequestBody long pointId) {
		if (pointId > 0)
			_fibrecablepointSvs.removeById(pointId);
		return R.ok();
	}

	@PostMapping("import")
	// "导入榄段设施", notes = "将数据以Excel的形式导入到数据库中")
	public R importExcel(@RequestParam("file") MultipartFile file, @RequestParam int deptId) throws Exception {
		// 获取用户上传表格的地址，执行完程序后表格将会删除，避免占用内存
		// 根据地址和文件名准确获取用户上传的表格
		// File tempFile = new File(file.getInputStream());
		try {
			// 将MultipartFile转换为File类型
			// file.transferTo(tempFile);
			String fileName = file.getOriginalFilename();
			String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
			InputStream in = file.getInputStream();
			InputStream inPoint = file.getInputStream();
			List<Map<String, String>> fibreList = ExcelImport.read(in, suffix, 1, 1, 0);
			String fibreCode = fibreList.get(0).get("光缆编码");
			if (StringUtils.isEmpty(fibreCode)) {
				return R.error(-1, "光缆编码必须填写！");
			}
			FibreFibre dbFibre = _fibreSvs
					.getOne(new QueryWrapper<FibreFibre>().eq("fibre_code", fibreCode).last("LIMIT 1"));
			if (dbFibre != null) {
				_fibreSvs.removeFibreAndPoints(dbFibre.getFibreId());
			}
			FibreFibre ff = new FibreFibre();
			for (Map<String, String> map : fibreList) {
				String fibreName = map.get("光缆名称");
				if (StringUtils.isEmpty(fibreName)) {
					return R.error(-1, "光缆名称必须填写！");
				}
				// String fbireCode = map.get("光缆编码");
				String fibreLevel = map.get("光缆类型");
				int coreCount = 0;
				if (StringUtils.isEmpty(map.get("纤芯数量"))) {
					return R.error(-1, "纤芯数量必须填写！");
				}
				try {
					coreCount = Integer.parseInt(map.get("纤芯数量"));
				} catch (Exception e) {
					return R.error(-1, "纤芯数量应为整数！");
				}
				String fibreModel = map.get("光缆型号");
				BigDecimal fibreLengthDecimal = null;
				// String fibreLength = map.get("光缆长度(km)");
				// if (StringUtils.isEmpty(fibreLength)) {
				// return R.error(-1, "光缆长度必须填写");
				// }
				// try {
				// fibreLengthDecimal = new BigDecimal(fibreLength);
				// } catch (Exception e) {
				// return R.error(-1, "光缆长度格式不正确");
				// }
				String supplier = map.get("生产厂家");
				String operationDate = map.get("投运时间");
				String serviceMobile = map.get("维护单位及电话");
				String remark = map.get("备注");

				ff.setDeptId(deptId);
				ff.setFibreName(fibreName);
				ff.setFibreLevel(fibreLevel);
				ff.setFibreCode(fibreCode);
				ff.setFibreModel(fibreModel);
				ff.setCoreCount(coreCount);
				ff.setFibreLength(fibreLengthDecimal);
				ff.setSupplier(supplier);

				if (!StringUtils.isEmpty(operationDate)) {
					try {
						ff.setOperationDate(DateUtils.stringToLocalDate(map.get("投运时间")));
					} catch (Exception e) {
						return R.error(-1, "投运时间格式不正确");
					}
				}

				ff.setRemark(remark);
				ff.setCreateBy(getUser().getUsername());
				ff.setCreateTime(LocalDateTime.now());
				ff.setServiceMobile(serviceMobile);
			}
			List<Map<String, String>> pointList = ExcelImport.read(inPoint, suffix, 3, 0, 2);
			List<FibreCablePoint> list = new ArrayList<FibreCablePoint>();
			String startLat = "", startLng = "";
			for (int i = 0; i < pointList.size(); i++) {
				if (StringUtils.isEmpty(pointList.get(i).get("序号"))) {
					continue;
				}
				int serialNum = Integer.parseInt(pointList.get(i).get("序号"));
				String pointCode = pointList.get(i).get("设施编码");
				String pointName = pointList.get(i).get("设施名称");
				if (StringUtils.isEmpty(pointList.get(i).get("设施类型"))) {
					return R.error(-1, "设施类型必须填写");
				}
				int pointType = Integer.parseInt(pointList.get(i).get("设施类型"));
				String norm = pointList.get(i).get("设施规格").toString();

				String distanceFromStart = pointList.get(i).get("距起点纤长(km)");
				if (StringUtils.isEmpty(distanceFromStart)) {
					return R.error(-1, "距起点纤长必须填写");
				}

				String lng = pointList.get(i).get("坐标经度");
				if (StringUtils.isEmpty(lng)) {
					return R.error(-1, "坐标经度必须填写");
				}
				String lat = pointList.get(i).get("坐标纬度");
				if (StringUtils.isEmpty(lat)) {
					return R.error(-1, "坐标纬度必须填写");
				}

				String obligateLength = pointList.get(i).get("预留纤长(m)");
				String remark = pointList.get(i).get("备注").toString();
				FibreCablePoint p = new FibreCablePoint();
				p.setSerialNum(serialNum);
				p.setPointCode(pointCode);
				p.setPointName(pointName);
				p.setPointType(pointType);
				BigDecimal distanceStart = new BigDecimal(distanceFromStart);
				p.setOrigoLength(distanceStart);
				p.setNorm(norm);
				p.setLng(lng);
				p.setLat(lat);
				if (StringUtils.isEmpty(obligateLength)) {
					p.setObligateLength(new BigDecimal(0));
				} else {
					p.setObligateLength(new BigDecimal(obligateLength));
				}
				p.setDeptId(getDeptId().intValue());
				p.setCreateTime(LocalDateTime.now());
				p.setCreateBy(getUser().getUsername());
				p.setRemark(remark);
				if (serialNum == 1) {
					startLat = lat;
					startLng = lng;
					p.setOrigoGpslength(new BigDecimal(0));
				} else {
					String disKM = GeoUtil.getDistanceMeterStr(startLat, startLng, lat, lng);
					p.setOrigoGpslength(new BigDecimal(disKM));
				}
				list.add(p);
			}
			ff.setFibreLength(list.get(list.size() - 1).getOrigoLength());
			boolean importResult = _fibreSvs.insertFibreAndPoints(ff, list);
			return R.trueOrFalse(importResult);
		} catch (Exception e) {
			log.error(e.toString());
			throw new Exception("批量录入设施失败，请检查表格中的数据是否合法！" + e.getMessage());
		}
	}

	@RequestMapping(value = "export")
	public R export(int fibreId) throws IOException {
		if (fibreId <= 0) {
			return R.error(-1, "参数错误");
		}
		FibreFibre fibre = _fibreSvs.getById(fibreId);
		if (fibre == null) {
			return R.error(-1, "未找到指定光缆信息");
		}
		HSSFWorkbook workbook = new HSSFWorkbook();
		HSSFSheet sheet = workbook.createSheet("光缆设施点详情报表");
		String dateString = DateUtils.formatLocalDateTime(LocalDateTime.now(), DateUtils.Pay_DATE_TIME_PATTERN);
		String fileName = fibre.getFibreName() + "光缆设施点详情报表" + dateString + ".xls";// 设置要导出的文件的名字

		Map<String, CellStyle> styles = ExcelImport.createStyles(workbook);

		// 新增数据行，并且设置单元格数据
		int rowNum = 0;
		String[] headers = { "光缆名称", "光缆编码", "光缆类型", "纤芯数量", "光缆型号", "光缆长度(km)", "生产厂家", "投运时间", "维护单位及电话", "备注" };

		rowNum = ExcelImport.initialize(rowNum, fibre.getFibreName() + "光缆设施点详情报表", headers, workbook, sheet, styles);

		// 在表中存放查询到的数据放入对应的列
		HSSFRow row1 = sheet.createRow(rowNum++);
		row1.createCell(0).setCellValue(fibre.getFibreName());
		row1.createCell(1).setCellValue(ExcelImport.convertNullString(fibre.getFibreCode()));
		row1.createCell(2).setCellValue(ExcelImport.convertNullString(fibre.getFibreLevel()));
		row1.createCell(3).setCellValue(ExcelImport.convertNullString(fibre.getCoreCount()));
		row1.createCell(4).setCellValue(ExcelImport.convertNullString(fibre.getFibreModel()));
		row1.createCell(5).setCellValue(ExcelImport.convertNullString(fibre.getFibreLength()));
		row1.createCell(6).setCellValue(ExcelImport.convertNullString(fibre.getSupplier()));
		row1.createCell(7).setCellValue(ExcelImport.convertNullString(fibre.getOperationDate()));
		row1.createCell(8).setCellValue(ExcelImport.convertNullString(fibre.getServiceMobile()));
		row1.createCell(9).setCellValue(ExcelImport.convertNullString(fibre.getRemark()));

		List<FibreCablePoint> list = _fibrecablepointSvs
				.list(new QueryWrapper<FibreCablePoint>().eq("fibre_id", fibreId));
		String[] headersPoints = { "序号", "设施编码", "设施名称", "设施类型", "设施规格", "距起点纤长（km）", "坐标经度", "坐标纬度", "预留纤长（m）", "备注" };
		rowNum = ExcelImport.initialize(rowNum, "", headersPoints, workbook, sheet, styles);
		for (FibreCablePoint point : list) {
			HSSFRow pointRow = sheet.createRow(rowNum++);
			pointRow.createCell(0).setCellValue(ExcelImport.convertNullString(point.getSerialNum()));
			pointRow.createCell(1).setCellValue(ExcelImport.convertNullString(point.getPointCode()));
			pointRow.createCell(2).setCellValue(ExcelImport.convertNullString(point.getPointName()));
			pointRow.createCell(3).setCellValue(ExcelImport.convertNullString(point.getPointType()));
			pointRow.createCell(4).setCellValue(ExcelImport.convertNullString(point.getNorm()));
			pointRow.createCell(5).setCellValue(ExcelImport.convertNullString(point.getOrigoLength()));
			pointRow.createCell(6).setCellValue(ExcelImport.convertNullString(point.getLng()));
			pointRow.createCell(7).setCellValue(ExcelImport.convertNullString(point.getLat()));
			pointRow.createCell(8).setCellValue(ExcelImport.convertNullString(point.getObligateLength()));
			pointRow.createCell(9).setCellValue(ExcelImport.convertNullString(point.getRemark()));
		}

		try {
			File path = new File(Constant.EXPORTPATH);
			if (!path.exists()) {
				path.mkdir();
			}
			File f = new File(path.getAbsolutePath() + "/excel/", fileName);
			if (!f.getParentFile().exists()) {
				f.getParentFile().mkdir();
			}
			FileOutputStream fileOutputStream = new FileOutputStream(f);// 指定路径与名字和格式
			workbook.write(fileOutputStream);// 将数据写出去
			fileOutputStream.close();// 关闭输出流
			return R.ok().putData("/excel/" + fileName);
		} catch (Exception e) {
			e.printStackTrace();
			return R.error(-1, e.getMessage());
		}
	}

}
